package nige.jar.classe;

import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Cherche des classes dans des fichiers jars
 * <br />- fichierJar : Fichier jar en cours d analyse
 * <br />- classeTrouve : Classe a chercher dans ce fichier
 * <br />- jfo : Resultat du scan
 * @author Nicolas Genevaux
 * 
 * DEPTH  2
 *       Object
 *       Thread
 * CALLEE  2
 *       ListeFichier
 *       TrouveClasse
 * 
 * 14-02-2008   Nicolas Genevaux      v.0.0.1
 */
public class TrouveClasse extends Thread {
  
  /**
   * fichierJar : Fichier jar en cours d analyse
   */
  private String fichierJar = "";
  /**
   * classeTrouve : Classe a chercher dans ce fichier
   */
  private String classeTrouve = "";
  /**
   * jfo : Resultat du scan
   */
  private JarFound jfo = new JarFound();
  /**
   * Permet de connaitre letat du thread
   */
  private boolean isAlive = true;
  
  /**
   * Constructeur de la classe
   * @param ofichierJar Fichier jar a scanner
   * @param oclasseTrouve Classe a trouver dans le fichier jar
   * @param ojf Objet contenant le resulat de la recherche
   */
  public TrouveClasse(String ofichierJar, 
      String oclasseTrouve, JarFound ojf) {
    jfo = ojf;
    fichierJar = ofichierJar;
    classeTrouve = oclasseTrouve;
  }
  
  /**
   * Permet de lancer le thread rattacher a la classe
   * Lance la fonction trouveClassesDansJar
   */
  public void run() {
    try {
      trouveClassesDansJar(fichierJar,classeTrouve);
    }
    catch(IOException e) {
      System.out.println("TrouveClasse : "+fichierJar+
          " - "+classeTrouve+" : "+e);
    }
  }
  
  /**
   * Cherche des classes dans un fichier jar
   * Incremente les jar scannes totaux et les thread lances
   * Realise une boucle tant qu il y a des elements dans le jar
   * @param fichierJar Fichier jar a scanner
   * @param classeTrouve Classe a chercher dans le fichier
   * @return ...  true si le fichier a ete trouve
   * @throws IOException Si le fichier jar n existe pas
   */
  private boolean trouveClassesDansJar(String fichierJar, String classeTrouve) 
      throws IOException {
    JarFile jf = new JarFile(fichierJar);
    jfo.setJarTotal(jfo.getJarTotal()+1);
    jfo.setThreadLaunch(jfo.getThreadLaunch()+1);
    Enumeration<JarEntry> enume = jf.entries();
    while(enume.hasMoreElements() && isAlive) {
      if(loopsToFindClasse(enume)) {
        return true;
      }
    }
    jfo.setThreadEnded(jfo.getThreadEnded()-1);
    return false;
  }
  
  /**
   * Boucle permettant de scanner le fichier jar
   * Transforme l element contenu dans le jar en un element comparable
   * Test le fichier scanne
   * Test pour voir si le fichier correspond a la classe scannee
   * @param enume Liste des objets contenu dans le fichier jar
   * @return ...  true si la classe a ete trouvee
   */
  private boolean loopsToFindClasse(Enumeration<JarEntry> enume) {
    jfo.setClasseTotal(jfo.getClasseTotal()+1);
    String classe = "";
    classe = enume.nextElement().toString().
        replaceAll("/",".").
          replaceAll(".class","");
    if((classe.indexOf(classeTrouve)>-1) && (jfo.getAllJars().indexOf(fichierJar)<0)) {
      loopsToFindClasseTestAJ();
    }
    if(classe.lastIndexOf(".")==(classe.length()-1)) {
      classe += "*";
    }
    String pack = classe.substring(0,classe.lastIndexOf(".")+1)+"*";
    if(pack.equals(classeTrouve) || classe.equals(classeTrouve)) {
      return loopsToFindClasseTestAJ();
    }
    else if(
        (pack.indexOf(classeTrouve)>-1 && 
            (pack.indexOf(classeTrouve)>=
              (pack.length()-classeTrouve.length()))) || 
        (classe.indexOf(classeTrouve)>-1 && 
            (classe.indexOf(classeTrouve)==
              (classe.length()-classeTrouve.length())))
      ) {
      return loopsToFindClasseTestAJ();
    }
    return false;
  }
  
  private boolean loopsToFindClasseTestAJ() {
    if(jfo.getAllJars().indexOf(fichierJar)<0) {
      jfo.getAllJars().add(fichierJar);
      jfo.setThreadEnded(jfo.getThreadEnded()-1);
    }
    return true;
  }

  /**
   * Provoque l interruption du thread
   * lors de la pression du bouton stop
   */
  public void arret() {
    isAlive = false;
  }
}

